package com.gitee.wsl.prism4j.languages

import com.gitee.wsl.ext.or
import com.gitee.wsl.prism4j.GrammarUtils
import com.gitee.wsl.prism4j.Prism4j
import com.gitee.wsl.prism4j.Prism4j.Companion.grammar
import com.gitee.wsl.prism4j.Prism4j.Companion.pattern
import com.gitee.wsl.prism4j.Prism4j.Companion.token
import com.gitee.wsl.prism4j.Prism4j.Pattern

@Suppress("unused")
//@Extend("clike")
object Prism_c {

    fun create(prism4j: Prism4j): Prism4j.Grammar {
        val c: Prism4j.Grammar = GrammarUtils.extend(
            GrammarUtils.require(prism4j, "clike"),
            "c",
            object : GrammarUtils.TokenFilter {
                override fun test(token: Prism4j.Token): Boolean {
                    val name = token.name()
                    return "class-name" != name && "boolean" != name
                }
            },
            token(
                "keyword",
                pattern(Pattern.compile("\\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\\b"))
            ),
            token(
                "operator",
                pattern(Pattern.compile("-[>-]?|\\+\\+?|!=?|<<?=?|>>?=?|==?|&&?|\\|\\|?|[~^%?*\\/]"))
            ),
            token(
                "number",
                pattern(
                    Pattern.compile(
                        "(?:\\b0x[\\da-f]+|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[+-]?\\d+)?)[ful]*",
                        Pattern.CASE_INSENSITIVE
                    )
                )
            )
        )

        GrammarUtils.insertBeforeToken(
            c, "string",
            token(
                "macro", pattern(
                    Pattern.compile(
                        "(^\\s*)#\\s*[a-z]+(?:[^\\r\\n\\\\]|\\\\(?:\\r\\n|[\\s\\S]))*",
                        Pattern.CASE_INSENSITIVE or Pattern.MULTILINE
                    ),
                    true,
                    false,
                    "property",
                    grammar(
                        "inside",
                        token(
                            "string",
                            pattern(
                                Pattern.compile("(#\\s*include\\s*)(?:<.+?>|(\"|')(?:\\\\?.)+?\\2)"),
                                true
                            )
                        ),
                        token(
                            "directive", pattern(
                                Pattern.compile("(#\\s*)\\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\\b"),
                                true,
                                false,
                                "keyword"
                            )
                        )
                    )
                )
            ),
            token(
                "constant",
                pattern(Pattern.compile("\\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\\b"))
            )
        )

        return c
    }
}
